package com.example.douyin.a.b;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ChannelInputShutdownEvent;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.util.CharsetUtil;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.*;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;

import javax.net.ssl.*;
import java.io.File;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import static io.netty.handler.codec.http.HttpHeaderNames.*;
import static io.netty.handler.codec.http.HttpMethod.CONNECT;
import static io.netty.handler.codec.http.HttpResponseStatus.*;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

public class WssSupportedProxy {
    private static final Log log = LogFactory.get();
    private static final int PROXY_PORT = Integer.getInteger("proxy.port", 8899);
    private static final int MAX_CONTENT_LENGTH = Integer.getInteger("max.content.length", 1048576); // 增大缓冲区到1MB（适配抖音大数据包）
    private static final int BOSS_THREADS = Integer.getInteger("boss.threads", 1);

    // 证书缓存相关
    private static final Map<String, KeyPair> certKeyPairCache = new ConcurrentHashMap<>();
    private static final Map<String, X509Certificate> certCache = new ConcurrentHashMap<>();
    private static final Map<String, SslContext> targetSslContextCache = new ConcurrentHashMap<>(); // 改为线程安全
    private static final ConcurrentHashMap<String, Object> certLocks = new ConcurrentHashMap<>();

    // 根证书配置（与生成的证书一致）
    private static final String MITM_KEYSTORE_PATH = "/Users/hanjiuri/IdeaProjects/douyin/src/main/resources/mitm-root.p12";
    private static final String MITM_KEYSTORE_PASS = "123456";
    private static final String MITM_KEY_ALIAS = "MITMProxy";

    // 抖音直播间常见WSS域名（必须添加到SAN，否则证书不匹配）
    private static final Set<String> DOUYIN_WSS_DOMAINS = new HashSet<>(Arrays.asList(
            "live.douyin.com",
            "webcast.amemv.com",
            "webcast3-ws-web-lf.douyin.com",
            "webcast5-ws-web-lf.douyin.com",
            "webcast-ws-web-lf.douyin.com",
            "webcast-amemv-web-lf.douyin.com",
            "ws-webcast.douyin.com"
    ));

    private static SslContext rootSslContext;
    private static X509Certificate rootCert;
    private static PrivateKey rootPrivateKey;
    private static CustomKeyManager keyManager;

    public static void main(String[] args) throws Exception {
        // 添加BouncyCastleProvider（必须）
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        CertificateExporter.exportRootCertificate();
        initRootCertAndPrivateKey();
        initRootSslContext();

        log.info("🎯 启动抖音WSS弹幕代理，端口: {}", PROXY_PORT);
        log.info("📌 支持的抖音WSS域名: {}", DOUYIN_WSS_DOMAINS);

        EventLoopGroup bossGroup = new NioEventLoopGroup(BOSS_THREADS);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap sb = new ServerBootstrap();
            sb.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, 15000) // 延长超时时间
                    .childOption(ChannelOption.TCP_NODELAY, true) // 禁用Nagle算法，减少延迟
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ChannelPipeline p = ch.pipeline();
                            p.addLast("httpCodec", new HttpServerCodec());
                            p.addLast("aggregator", new HttpObjectAggregator(MAX_CONTENT_LENGTH));
                            p.addLast("proxyHandler", new WssProxyHandler());
                        }
                    });

            Channel ch = sb.bind(PROXY_PORT).sync().channel();
            log.info("🟢 代理服务器已启动，等待浏览器连接...");
            ch.closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    /**
     * 初始化根证书和私钥（验证有效性）
     */
    private static void initRootCertAndPrivateKey() throws Exception {
        try (FileInputStream fis = new FileInputStream(MITM_KEYSTORE_PATH)) {
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            keyStore.load(fis, MITM_KEYSTORE_PASS.toCharArray());

            rootCert = (X509Certificate) keyStore.getCertificate(MITM_KEY_ALIAS);
            // 打印根证书SHA-256指纹
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] fingerprint = md.digest(rootCert.getEncoded());
            StringBuilder sb = new StringBuilder();
            for (byte b : fingerprint) {
                sb.append(String.format("%02X:", b));
            }
            String fingerprintStr = sb.substring(0, sb.length() - 1);
            log.info("✅ 根证书SHA-256指纹：{}", fingerprintStr);

            // 验证私钥存在
            Key key = keyStore.getKey(MITM_KEY_ALIAS, MITM_KEYSTORE_PASS.toCharArray());
            if (!(key instanceof PrivateKey)) throw new RuntimeException("根证书私钥不存在");
            rootPrivateKey = (PrivateKey) key;

            // 验证证书有效性（自签名+有效期）
            rootCert.checkValidity();
            Signature sig = Signature.getInstance("SHA256withRSA");
            sig.initSign(rootPrivateKey);
            sig.update("douyin-proxy-test".getBytes());
            sig.sign();
            rootCert.verify(rootCert.getPublicKey());

            log.info("✅ 根证书验证通过，主题: {}", rootCert.getSubjectDN());
            log.info("✅ 根证书有效期: {} 至 {}", rootCert.getNotBefore(), rootCert.getNotAfter());
        }
    }

    /**
     * 初始化根SSL上下文（支持动态证书）
     */
    private static void initRootSslContext() throws Exception {
        keyManager = new CustomKeyManager();
        rootSslContext = SslContextBuilder.forServer(keyManager)
                .protocols("TLSv1.2", "TLSv1.3") // 优先TLSv1.2（抖音兼容更好）
                .ciphers(null) // 使用默认加密套件
                .sessionTimeout(3600) // 延长会话超时
                .build();
        log.info("✅ SSL上下文初始化完成（支持抖音WSS动态证书）");
    }
    /**
     * 根证书验证工具
     */
    public static void verifyRootCertificateInstallation() {
        try {
            // 重新加载根证书
            FileInputStream fis = new FileInputStream(MITM_KEYSTORE_PATH);
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            keyStore.load(fis, MITM_KEYSTORE_PASS.toCharArray());

            X509Certificate rootCert = (X509Certificate) keyStore.getCertificate(MITM_KEY_ALIAS);

            // 验证根证书基本信息
            log.info("🔍 根证书验证:");
            log.info("   主题: {}", rootCert.getSubjectX500Principal());
            log.info("   签发者: {}", rootCert.getIssuerX500Principal());
            log.info("   序列号: {}", rootCert.getSerialNumber());
            log.info("   有效期: {} 到 {}", rootCert.getNotBefore(), rootCert.getNotAfter());

            // 检查是否为自签名
            try {
                rootCert.verify(rootCert.getPublicKey());
                log.info("   ✅ 根证书是自签名的");
            } catch (Exception e) {
                log.info("   ❌ 根证书不是自签名的");
            }

            // 导出供手动验证
            String pem = "-----BEGIN CERTIFICATE-----\n" +
                    Base64.getMimeEncoder().encodeToString(rootCert.getEncoded()) +
                    "\n-----END CERTIFICATE-----";

            Files.write(Paths.get("root-cert-debug.crt"), pem.getBytes());
            log.info("   📁 根证书已保存到: root-cert-debug.crt");

        } catch (Exception e) {
            log.error("根证书验证失败", e);
        }
    }
    /**
     * 生成更符合标准的SSL证书
     */
    private static X509Certificate generateStandardCertificate(String targetHost) throws Exception {
        // 使用缓存
        X509Certificate cached = certCache.get(targetHost);
        if (cached != null) return cached;

        Object lock = certLocks.computeIfAbsent(targetHost, k -> new Object());
        synchronized (lock) {
            if (certCache.containsKey(targetHost)) return certCache.get(targetHost);

            // 生成密钥对
            KeyPair keyPair = certKeyPairCache.computeIfAbsent(targetHost, k -> {
                try {
                    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
                    kpg.initialize(2048, new SecureRandom());
                    return kpg.generateKeyPair();
                } catch (Exception ex) {
                    throw new RuntimeException("生成密钥对失败", ex);
                }
            });

            // 证书有效期（适当缩短，避免被怀疑）
            Calendar calendar = Calendar.getInstance();
            Date notBefore = calendar.getTime();
            calendar.add(Calendar.DAY_OF_YEAR, 30); // 30天有效期
            Date notAfter = calendar.getTime();

            // 证书主体信息
            X500Name issuer = new X500Name(rootCert.getSubjectX500Principal().getName());
            X500Name subject = new X500Name("CN=" + targetHost + ", O=Security Proxy, C=CN");
            BigInteger serial = BigInteger.valueOf(System.currentTimeMillis());

            // 构建证书
            X509v3CertificateBuilder builder = new X509v3CertificateBuilder(
                    issuer, serial, notBefore, notAfter, subject,
                    SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded())
            );

            // SAN扩展 - 包含目标域名和通配符
            List<GeneralName> sanList = new ArrayList<>();
            sanList.add(new GeneralName(GeneralName.dNSName, targetHost));

            // 添加通配符域名
            if (targetHost.contains(".")) {
                String baseDomain = targetHost.substring(targetHost.indexOf(".") + 1);
                String wildcardDomain = "*." + baseDomain;
                sanList.add(new GeneralName(GeneralName.dNSName, wildcardDomain));
            }

            builder.addExtension(Extension.subjectAlternativeName, false,
                    new GeneralNames(sanList.toArray(new GeneralName[0])));

            // 标准扩展
            builder.addExtension(Extension.basicConstraints, true, new BasicConstraints(false));
            builder.addExtension(Extension.keyUsage, true,
                    new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment | KeyUsage.keyAgreement));
            builder.addExtension(Extension.extendedKeyUsage, false,
                    new ExtendedKeyUsage(new KeyPurposeId[]{KeyPurposeId.id_kp_serverAuth}));

            // 签名
            ContentSigner signer = new JcaContentSignerBuilder("SHA256withRSA")
                    .setProvider("BC")
                    .build(rootPrivateKey);

            X509Certificate cert = new JcaX509CertificateConverter()
                    .setProvider("BC")
                    .getCertificate(builder.build(signer));

            // 验证证书链
            cert.verify(rootCert.getPublicKey());

            certCache.put(targetHost, cert);
            certLocks.remove(targetHost);

            log.info("✅ 生成标准SSL证书: {}", targetHost);
            return cert;
        }
    }

    /**
     * 获取目标服务器SSL上下文（抖音WSS用）
     */
    private static SslContext getTargetSslContext(String targetHost) throws Exception {
        return targetSslContextCache.computeIfAbsent(targetHost, k -> {
            try {
                return SslContextBuilder.forClient()
                        .trustManager(InsecureTrustManagerFactory.INSTANCE) // 信任所有目标证书（抖音可能用自签名）
                        .protocols("TLSv1.2", "TLSv1.3")
                        .build();
            } catch (Exception e) {
                throw new RuntimeException("创建目标SSL上下文失败", e);
            }
        });
    }

    /**
     * 自定义KeyManager（动态返回目标站点证书）
     */
    private static class CustomKeyManager extends X509ExtendedKeyManager {
        private final ThreadLocal<String> sniHostname = new ThreadLocal<>();
        private String fallbackHost;

        @Override
        public String[] getClientAliases(String keyType, Principal[] issuers) { return null; }

        @Override
        public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { return null; }

        @Override
        public String[] getServerAliases(String keyType, Principal[] issuers) { return new String[]{"dynamic-cert"}; }

        @Override
        public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { return "dynamic-cert"; }

        @Override
        public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) {
            // 从SNI获取目标域名（抖音WSS连接会携带SNI）
            String host = null;
            SSLSession session = engine.getHandshakeSession();
            if (session instanceof ExtendedSSLSession) {
                List<SNIServerName> sniNames = ((ExtendedSSLSession) session).getRequestedServerNames();
                if (sniNames != null && !sniNames.isEmpty()) {
                    for (SNIServerName name : sniNames) {
                        if (name.getType() == StandardConstants.SNI_HOST_NAME) {
                            host = ((SNIHostName) name).getAsciiName();
                            break;
                        }
                    }
                }
            }
            // 降级使用fallbackHost
            if (host == null) host = fallbackHost != null ? fallbackHost : "localhost";
            sniHostname.set(host);
            log.debug("📡 SSL握手：客户端请求域名={}", host);
            return "dynamic-cert";
        }

        @Override
        public X509Certificate[] getCertificateChain(String alias) {
            String host = sniHostname.get();
            if (host == null) host = fallbackHost != null ? fallbackHost : "localhost";

            try {
                log.info("🔐 为域名 {} 生成证书链", host);
                X509Certificate cert = generateStandardCertificate(host);

                // 详细日志证书信息
                log.info("📄 证书主题: {}", cert.getSubjectX500Principal());
                log.info("📄 证书签发者: {}", cert.getIssuerX500Principal());
                log.info("📄 证书有效期: {} 到 {}", cert.getNotBefore(), cert.getNotAfter());
                log.info("📄 证书SHA-256: {}", getCertFingerprint(cert));

                return new X509Certificate[]{cert, rootCert};
            } catch (Exception e) {
                log.error("❌ 生成证书链失败", e);
                throw new RuntimeException(e);
            }
        }

        private String getCertFingerprint(X509Certificate cert) throws Exception {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] fingerprint = md.digest(cert.getEncoded());
            StringBuilder sb = new StringBuilder();
            for (byte b : fingerprint) {
                sb.append(String.format("%02X", b));
            }
            return sb.toString();
        }

        @Override
        public PrivateKey getPrivateKey(String alias) {
            String host = sniHostname.get();
            if (host == null) host = fallbackHost != null ? fallbackHost : "localhost";
            try {
                KeyPair kp = certKeyPairCache.get(host);
                return kp != null ? kp.getPrivate() : rootPrivateKey;
            } finally {
                sniHostname.remove();
            }
        }

        public void setFallbackHost(String host) { this.fallbackHost = host; }
    }

    /**
     * 核心代理处理器（处理HTTP/HTTPS/WSS请求）
     */
    public static class WssProxyHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
        private Channel outboundChannel;
        private boolean isWebSocket = false;
        private String targetHost;
        private int targetPort;

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) {
            if (!request.decoderResult().isSuccess()) {
                sendErrorResponse(ctx, BAD_REQUEST, "请求解析失败");
                request.release();
                return;
            }

            String host = request.headers().get(HOST);
            isWebSocket = isWebSocketUpgrade(request);

            // 打印WSS连接信息
            if (isWebSocket) {
                log.info("\n====== 🔗 WSS连接请求 ======");
                log.info("主机: {}", host);
                log.info("URI: {}", request.uri());
                log.info("Sec-WebSocket-Key: {}", request.headers().get("Sec-WebSocket-Key"));
                log.info("Sec-WebSocket-Version: {}", request.headers().get("Sec-WebSocket-Version"));
                log.info("==============================\n");
            }

            forwardRequest(ctx, host, request);
        }

        /**
         * 判断是否为WebSocket升级请求
         */
        private boolean isWebSocketUpgrade(FullHttpRequest request) {
            return request.method() == HttpMethod.GET &&
                    request.headers().contains(UPGRADE) &&
                    "websocket".equalsIgnoreCase(request.headers().get(UPGRADE)) &&
                    request.headers().contains(CONNECTION) &&
                    request.headers().get(CONNECTION).toLowerCase().contains("upgrade");
        }

        /**
         * 转发请求到目标服务器（HTTP/HTTPS/WSS）
         */
        private void forwardRequest(ChannelHandlerContext ctx, String host, FullHttpRequest request) {
            if (host == null) {
                sendErrorResponse(ctx, BAD_REQUEST, "缺少Host头信息");
                request.release();
                return;
            }

            // 解析目标主机和端口
            String[] hostParts = host.split(":");
            targetHost = hostParts[0];
            // 抖音WSS默认端口443，HTTP默认80
            targetPort = (hostParts.length > 1) ? Integer.parseInt(hostParts[1]) :
                    (request.method() == CONNECT ? 443 : 80);

            // 设置证书 fallbackHost（确保动态证书生成正确）
            keyManager.setFallbackHost(targetHost);
            log.debug("📤 转发请求：{}:{} {} {}", targetHost, targetPort, request.method(), request.uri());

            // 处理HTTPS CONNECT请求（WSS基于HTTPS隧道）
            if (request.method() == CONNECT) {
                handleHttpsConnect(ctx, host, request);
                return;
            }

            // 处理HTTP/WebSocket（非加密）请求
            Bootstrap b = new Bootstrap();
            b.group(ctx.channel().eventLoop())
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 15000)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ChannelPipeline p = ch.pipeline();
                            p.addLast(new HttpClientCodec());
                            p.addLast(new HttpObjectAggregator(MAX_CONTENT_LENGTH));
                            if (isWebSocket) {
                                p.addLast(new WebSocketFrameAggregator(MAX_CONTENT_LENGTH));
                                p.addLast(new WebSocketMessageHandler(ctx.channel(), false)); // 客户端->服务端
                            }
                            p.addLast(new TargetHandler(ctx.channel()));
                        }
                    });

            ChannelFuture f = b.connect(targetHost, targetPort);
            outboundChannel = f.channel();

            f.addListener((ChannelFuture future) -> {
                if (future.isSuccess()) {
                    log.debug("✅ 成功连接目标服务器: {}:{}", targetHost, targetPort);
                    // 转发请求（复制原始请求，避免引用计数问题）
                    DefaultFullHttpRequest newRequest = createNewRequest(request);
                    future.channel().writeAndFlush(newRequest);
                } else {
                    log.error("❌ 连接目标服务器失败: {}:{}", targetHost, targetPort, future.cause());
                    sendErrorResponse(ctx, BAD_GATEWAY, "无法连接到目标服务器: " + host);
                    request.release();
                }
            });
        }

        /**
         * 处理HTTPS CONNECT隧道（WSS核心）
         */
        private void handleHttpsConnect(ChannelHandlerContext ctx, String host, FullHttpRequest request) {
            // 发送200 OK响应，告知浏览器隧道建立成功
            FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK);
            ctx.writeAndFlush(response).addListener((ChannelFuture future) -> {
                if (!future.isSuccess()) {
                    log.error("❌ HTTPS隧道响应发送失败", future.cause());
                    ctx.close();
                    request.release();
                    return;
                }
                log.debug("✅ HTTPS隧道建立成功（浏览器->代理）");

                // 移除HTTP相关处理器，切换为SSL+WSS处理
                ChannelPipeline clientPipeline = ctx.pipeline();
                clientPipeline.remove("httpCodec");
                clientPipeline.remove("aggregator");
                clientPipeline.remove("proxyHandler");

                try {
                    // 添加客户端SSL处理器（代理->浏览器加密）
                    SslHandler clientSsl = rootSslContext.newHandler(ctx.alloc());
                    // 监听SSL握手结果
                    clientSsl.handshakeFuture().addListener(f -> {
                        if (f.isSuccess()) {
                            log.info("✅ SSL握手成功（浏览器<->代理）: {}", ctx.channel().remoteAddress());
                        } else {
                            log.error("❌ SSL握手失败（浏览器<->代理）", f.cause());
                            ctx.close();
                        }
                    });
                    clientPipeline.addFirst("clientSsl", clientSsl);

                    // 重新添加HTTP处理器，用于解析WSS升级请求（解密后）
                    clientPipeline.addLast("httpCodec", new HttpServerCodec());
                    clientPipeline.addLast("aggregator", new HttpObjectAggregator(MAX_CONTENT_LENGTH));
                    clientPipeline.addLast("wssDetector", new WssDetectorHandler(ctx.channel()));
                } catch (Exception e) {
                    log.error("❌ 初始化客户端SSL处理器失败", e);
                    ctx.close();
                }
            });

            // 连接目标服务器（代理->抖音WSS服务器）
            Bootstrap b = new Bootstrap();
            b.group(ctx.channel().eventLoop())
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 15000)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ChannelPipeline p = ch.pipeline();
                            try {
                                // 添加目标服务器SSL处理器（代理->抖音加密）
                                SslContext targetSslContext = getTargetSslContext(targetHost);
                                SslHandler targetSsl = targetSslContext.newHandler(ch.alloc(), targetHost, targetPort);
                                targetSsl.handshakeFuture().addListener(f -> {
                                    if (f.isSuccess()) {
                                        log.info("✅ SSL握手成功（代理<->抖音服务器）: {}:{}", targetHost, targetPort);
                                    } else {
                                        log.error("❌ SSL握手失败（代理<->抖音服务器）", f.cause());
                                        ch.close();
                                    }
                                });
                                p.addFirst("targetSsl", targetSsl);

                                // 添加HTTP处理器，解析抖音WSS响应
                                p.addLast(new HttpClientCodec());
                                p.addLast(new HttpObjectAggregator(MAX_CONTENT_LENGTH));
                                p.addLast(new TargetHandler(ctx.channel()));
                            } catch (Exception e) {
                                log.error("❌ 初始化目标服务器SSL处理器失败", e);
                                ch.close();
                            }
                        }
                    });

            ChannelFuture f = b.connect(targetHost, targetPort);
            outboundChannel = f.channel();

            f.addListener((ChannelFuture future) -> {
                if (!future.isSuccess()) {
                    log.error("❌ HTTPS隧道连接抖音服务器失败: {}:{}", targetHost, targetPort, future.cause());
                    sendErrorResponse(ctx, BAD_GATEWAY, "无法建立HTTPS隧道: " + host);
                    request.release();
                }
            });
        }

        /**
         * 复制原始HTTP请求（避免Netty引用计数问题）
         */
        private DefaultFullHttpRequest createNewRequest(FullHttpRequest original) {
            DefaultFullHttpRequest newRequest = new DefaultFullHttpRequest(
                    original.protocolVersion(), original.method(), original.uri()
            );
            newRequest.headers().setAll(original.headers());
            newRequest.content().writeBytes(original.content());
            newRequest.trailingHeaders().setAll(original.trailingHeaders());
            // 保留原始请求的引用计数（Netty需手动管理）
            original.retain();
            return newRequest;
        }

        /**
         * 发送错误响应给浏览器
         */
        private void sendErrorResponse(ChannelHandlerContext ctx, HttpResponseStatus status, String message) {
            FullHttpResponse response = new DefaultFullHttpResponse(
                    HTTP_1_1, status, Unpooled.copiedBuffer(message, CharsetUtil.UTF_8)
            );
            response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
            response.headers().set(CONTENT_LENGTH, response.content().readableBytes());
            ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
        }

        @Override
        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
            if (evt instanceof ChannelInputShutdownEvent && outboundChannel != null) {
                log.debug("🔌 客户端输入流关闭，关闭目标通道");
                closeOnFlush(outboundChannel);
            }
            super.userEventTriggered(ctx, evt);
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            log.error("❌ 客户端连接异常", cause);
            closeOnFlush(ctx.channel());
            if (outboundChannel != null) {
                closeOnFlush(outboundChannel);
            }
        }

        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            log.debug("🔌 客户端通道关闭: {}", ctx.channel().remoteAddress());
            if (outboundChannel != null) {
                closeOnFlush(outboundChannel);
            }
            super.channelInactive(ctx);
        }
    }

    /**
     * WSS检测处理器（解密后识别WebSocket升级请求）
     */
    public static class WssDetectorHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
        private final Channel clientChannel;
        private boolean switched = false;

        public WssDetectorHandler(Channel clientChannel) {
            this.clientChannel = clientChannel;
        }

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) {
            if (!switched && isWebSocketUpgrade(request)) {
                log.info("\n====== 🔗 WSS连接请求（解密后）======");
                log.info("主机: {}", request.headers().get(HOST));
                log.info("URI: {}", request.uri());
                log.info("Sec-WebSocket-Key: {}", request.headers().get("Sec-WebSocket-Key"));
                log.info("Sec-WebSocket-Version: {}", request.headers().get("Sec-WebSocket-Version"));
                log.info("====================================\n");

                // 切换为WebSocket处理器
                ChannelPipeline pipeline = ctx.pipeline();
                pipeline.remove("httpCodec");
                pipeline.remove("aggregator");
                pipeline.remove("wssDetector");
                pipeline.addLast(new WebSocketFrameAggregator(MAX_CONTENT_LENGTH));
                pipeline.addLast(new WebSocketMessageHandler(clientChannel, false)); // 代理->抖音
                switched = true;

                // 转发WSS升级请求到抖音服务器
                ctx.channel().writeAndFlush(copyRequest(request));
            } else {
                // 非WSS请求直接转发
                if (ctx.channel().isActive()) {
                    ctx.channel().writeAndFlush(copyRequest(request));
                } else {
                    request.release();
                }
            }
        }

        /**
         * 判断是否为WebSocket升级请求
         */
        private boolean isWebSocketUpgrade(FullHttpRequest request) {
            return request.method() == HttpMethod.GET &&
                    "websocket".equalsIgnoreCase(request.headers().get(UPGRADE)) &&
                    request.headers().get(CONNECTION).toLowerCase().contains("upgrade");
        }

        /**
         * 复制HTTP请求
         */
        private FullHttpRequest copyRequest(FullHttpRequest original) {
            DefaultFullHttpRequest copy = new DefaultFullHttpRequest(
                    original.protocolVersion(), original.method(), original.uri()
            );
            copy.headers().setAll(original.headers());
            copy.content().writeBytes(original.content());
            original.retain();
            return copy;
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            log.error("❌ WSS检测处理器异常", cause);
            closeOnFlush(ctx.channel());
            closeOnFlush(clientChannel);
        }
    }

    /**
     * 目标服务器响应处理器（抖音->代理）
     */
    public static class TargetHandler extends SimpleChannelInboundHandler<FullHttpResponse> {
        private final Channel inboundChannel;

        public TargetHandler(Channel inboundChannel) {
            this.inboundChannel = inboundChannel;
        }

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, FullHttpResponse response) {
            // 检测WebSocket升级响应（101 Switching Protocols）
            if (response.status().code() == 101 &&
                    "websocket".equalsIgnoreCase(response.headers().get("Upgrade"))) {
                log.info("🎉 WSS连接建立成功（抖音<->代理<->浏览器）");
                log.info("📢 开始捕获抖音直播间弹幕数据...\n");

                // 切换客户端通道为WebSocket处理器
                ChannelPipeline pipeline = inboundChannel.pipeline();
                if (pipeline.get("httpCodec") != null) pipeline.remove("httpCodec");
                if (pipeline.get("aggregator") != null) pipeline.remove("aggregator");
                if (pipeline.get("proxyHandler") != null) pipeline.remove("proxyHandler");
                pipeline.addLast(new WebSocketFrameAggregator(MAX_CONTENT_LENGTH));
                pipeline.addLast(new WebSocketMessageHandler(ctx.channel(), true)); // 抖音->客户端
            }

            // 转发响应给浏览器
            DefaultFullHttpResponse newResponse = createNewResponse(response);
            inboundChannel.writeAndFlush(newResponse);
        }

        /**
         * 复制HTTP响应（处理Netty引用计数）
         */
        private DefaultFullHttpResponse createNewResponse(FullHttpResponse original) {
            DefaultFullHttpResponse newResponse = new DefaultFullHttpResponse(
                    original.protocolVersion(), original.status()
            );
            newResponse.headers().setAll(original.headers());
            newResponse.content().writeBytes(original.content());
            newResponse.trailingHeaders().setAll(original.trailingHeaders());
            original.release(); // 释放原始响应
            return newResponse;
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            log.error("❌ 目标服务器响应处理器异常", cause);
            closeOnFlush(inboundChannel);
            closeOnFlush(ctx.channel());
        }

        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            log.debug("🔌 目标服务器通道关闭: {}", ctx.channel().remoteAddress());
            closeOnFlush(inboundChannel);
            super.channelInactive(ctx);
        }
    }

    /**
     * WebSocket消息处理器（核心：捕获抖音弹幕数据）
     */
    public static class WebSocketMessageHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
        private final Channel peerChannel;
        private final boolean isServerToClient; // true: 抖音->客户端（弹幕数据）

        public WebSocketMessageHandler(Channel peerChannel, boolean isServerToClient) {
            this.peerChannel = peerChannel;
            this.isServerToClient = isServerToClient;
        }

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) {
            try {
                // 处理文本消息（部分抖音通知可能为文本）
                if (frame instanceof TextWebSocketFrame) {
                    String text = ((TextWebSocketFrame) frame).text();
                    log.info("[WebSocket {}] 文本消息: {}",
                            isServerToClient ? "📥 抖音->客户端" : "📤 客户端->抖音", text);
                }
                // 处理二进制消息（抖音弹幕核心数据，Protobuf格式）
                else if (frame instanceof BinaryWebSocketFrame) {
                    ByteBuf content = frame.content();
                    int length = content.readableBytes();
                    byte[] data = new byte[length];
                    content.readBytes(data); // 读取完整二进制数据

                    log.info("\n[WebSocket {}] 二进制消息（弹幕数据）: 长度={}字节",
                            isServerToClient ? "📥 抖音->客户端" : "📤 客户端->抖音", length);
                    log.debug("前32字节十六进制: {}", bytesToHex(Arrays.copyOfRange(data, 0, Math.min(length, 32))));
                    log.debug("Base64编码: {}", Base64.getEncoder().encodeToString(data));

                    // TODO: 抖音弹幕Protobuf解码（需逆向protobuf协议）
                    // 示例：如果已有protobuf定义，可直接解码
                    // DanmuProto.Danmu danmu = DanmuProto.Danmu.parseFrom(data);
                    // log.info("弹幕内容: {} | 发送者: {} | 礼物: {}", danmu.getContent(), danmu.getUserName(), danmu.getGiftName());
                }
                // 处理Ping/Pong消息（维持连接）
                else if (frame instanceof PingWebSocketFrame) {
                    log.debug("[WebSocket] 🛡️ Ping消息");
                    peerChannel.writeAndFlush(new PongWebSocketFrame(frame.content().retain()));
                    return;
                } else if (frame instanceof PongWebSocketFrame) {
                    log.debug("[WebSocket] 🛡️ Pong消息");
                }
                // 处理关闭连接消息
                else if (frame instanceof CloseWebSocketFrame) {
                    CloseWebSocketFrame closeFrame = (CloseWebSocketFrame) frame;
                    log.info("[WebSocket] 🚫 关闭连接: 状态码={}, 原因={}",
                            closeFrame.statusCode(), closeFrame.reasonText());
                    peerChannel.writeAndFlush(frame.retain());
                    closeOnFlush(ctx.channel());
                    return;
                } else {
                    log.warn("[WebSocket] ❓ 未知帧类型: {}", frame.getClass().getSimpleName());
                }

                // 转发消息到对端（确保连接不中断）
                if (peerChannel.isActive()) {
                    peerChannel.writeAndFlush(frame.retain());
                } else {
                    frame.release();
                }
            } catch (Exception e) {
                log.error("❌ WebSocket消息处理异常", e);
                closeOnFlush(ctx.channel());
                closeOnFlush(peerChannel);
            }
        }

        /**
         * 字节数组转十六进制字符串（便于调试二进制数据）
         */
        private String bytesToHex(byte[] bytes) {
            if (bytes == null || bytes.length == 0) return "";
            StringBuilder sb = new StringBuilder();
            for (byte b : bytes) {
                sb.append(String.format("%02x ", b));
            }
            return sb.toString().trim();
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            log.error("❌ WebSocket消息处理器异常", cause);
            closeOnFlush(ctx.channel());
            closeOnFlush(peerChannel);
        }

        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            log.debug("🔌 WebSocket通道关闭: {}", isServerToClient ? "抖音->客户端" : "客户端->抖音");
            closeOnFlush(peerChannel);
            super.channelInactive(ctx);
        }
    }

    /**
     * 隧道处理器（备用，处理纯WebSocket的纯TCP转发）
     */
    public static class TunnelHandler extends ChannelInboundHandlerAdapter {
        private final Channel peerChannel;

        public TunnelHandler(Channel peerChannel) {
            this.peerChannel = peerChannel;
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            if (peerChannel.isActive()) {
                peerChannel.writeAndFlush(msg);
            } else {
                if (msg instanceof ByteBuf) {
                    ((ByteBuf) msg).release();
                }
            }
        }

        @Override
        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
            if (evt instanceof ChannelInputShutdownEvent) {
                closeOnFlush(peerChannel);
            }
            super.userEventTriggered(ctx, evt);
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            log.error("❌ 隧道连接异常", cause);
            closeOnFlush(ctx.channel());
            closeOnFlush(peerChannel);
        }
    }

    /**
     * 优雅关闭通道（确保数据发送完成）
     */
    static void closeOnFlush(Channel ch) {
        if (ch != null && ch.isActive()) {
            ch.writeAndFlush(Unpooled.EMPTY_BUFFER)
                    .addListener(ChannelFutureListener.CLOSE)
                    .addListener(future -> {
                        if (!future.isSuccess()) {
                            log.warn("⚠️ 通道关闭失败", future.cause());
                        }
                    });
        }
    }
    /**
     * 证书导出工具类
     */
    public static class CertificateExporter {

        /**
         * 导出根证书为PEM格式文件
         */
        public static void exportRootCertificate() {
            try {
                // 从您的PKCS12文件中提取根证书
                FileInputStream fis = new FileInputStream(MITM_KEYSTORE_PATH);
                KeyStore keyStore = KeyStore.getInstance("PKCS12");
                keyStore.load(fis, MITM_KEYSTORE_PASS.toCharArray());

                X509Certificate rootCert = (X509Certificate) keyStore.getCertificate(MITM_KEY_ALIAS);

                // 导出为PEM文件
                String pemContent = "-----BEGIN CERTIFICATE-----\n" +
                        Base64.getEncoder().encodeToString(rootCert.getEncoded()) +
                        "\n-----END CERTIFICATE-----";

                File certFile = new File("mitm-proxy-root.crt");
                Files.write(certFile.toPath(), pemContent.getBytes(StandardCharsets.UTF_8));

                log.info("✅ 根证书已导出到: {}", certFile.getAbsolutePath());
                log.info("📋 请将此证书导入到浏览器的信任根证书颁发机构中");

            } catch (Exception e) {
                log.error("❌ 导出根证书失败", e);
            }
        }
    }
}
